﻿Imports Microsoft.Win32

Public Class RegistryStoredFolderValuesCollection
    Inherits System.Collections.Generic.List(Of RegistryStoredFolderValues)

    Private WithEvents Timer As System.Timers.Timer
    Private _regKey As RegistryKey

    Friend Const KEY_PATH As String = "Software\DeleteEmails"

    Public Sub New()
        MyBase.New()
        Me.Timer = New Timers.Timer(500)
        Me.Timer.AutoReset = False
        Me.Timer.Enabled = False
        LoadValues()
    End Sub

    Public Sub LoadValues()
        Dim subkey As RegistryKey
        For Each i As String In Key.GetSubKeyNames()
            subkey = Key.OpenSubKey(i)
            Me.Add(New RegistryStoredFolderValues(subkey))
            subkey.Close()
        Next
    End Sub

    Private ReadOnly Property Key As RegistryKey
        Get
            If _regKey Is Nothing Then
                _regKey = Registry.CurrentUser.OpenSubKey(KEY_PATH, True)
                If _regKey Is Nothing Then _regKey = Registry.CurrentUser.CreateSubKey(KEY_PATH,  RegistryKeyPermissionCheck.ReadWriteSubTree)
            End If
            Timer.Enabled = True
            Return _regKey
        End Get
    End Property

    Private Sub CloseKey(ByVal sender As Object, ByVal e As Timers.ElapsedEventArgs) Handles Timer.Elapsed
        If Not _regkey Is Nothing Then
            _regkey.Close()
            _regkey = Nothing
        End If
        Timer.Enabled = False
    End Sub

    Public Shadows Sub Add(ByVal item As RegistryStoredFolderValues)
        If Not item.IsValid() Then Exit Sub
        If Me.Contains(item) Then Me.Replace(item)
        MyBase.Add(item)
        Key.CreateSubKey(item.Name)
        Dim subkey As RegistryKey = Key.OpenSubKey(item.Name, True)
        item.SetAllValues(subkey)
    End Sub

    Public Shadows Function Contains(ByVal item As RegistryStoredFolderValues) As Boolean
        Return Me.FindByName(item.Name).IsValid()
    End Function

    Public Shadows Function Contains(ByVal item As FolderDeleteOptions) As Boolean
        Return Me.FindByName(item.KeyName).IsValid()
    End Function

    Public Sub Replace(ByVal item As RegistryStoredFolderValues)
        If Not item.IsValid() Then Exit Sub
        If Not Me.Contains(item) Then Me.Add(item)
        Dim olditem As Integer = MyBase.FindIndex(Function(x As RegistryStoredFolderValues)
                                                      Return (x.Name = item.Name)
                                                  End Function)
        MyBase.Item(olditem) = item
        Dim subkey As RegistryKey = Key.OpenSubKey(item.Name)
        item.SetAllValues(subkey)
    End Sub

    Public Shadows Function Remove(ByVal item As RegistryStoredFolderValues) As Boolean
        If MyBase.Remove(item) Then
            Key.DeleteSubKey(item.Name, False)
            Return True
        End If
        Return False
    End Function

    Public Function FindByName(ByVal Name As String) As RegistryStoredFolderValues
        Return MyBase.Find(Function(x As RegistryStoredFolderValues)
                               Return (x.Name = Name)
                           End Function)
    End Function

End Class

Public Structure RegistryStoredFolderValues

    Private Const FOLDER_PATH_NAME As String = "FolderPath"
    Private Const TIME_VALUE_NAME As String = "TimeValue"
    Private Const TIME_UNITS_NAME As String = "TimeUnits"
    Private Const DISABLED_NAME As String = "Disabled"

    Public Name As String
    Public FolderPath As String
    Public TimeValue As UInteger
    Public TimeUnits As Byte
    Public Disabled As Boolean
    'Public CurrentIndex As Integer

    Public Sub New(ByVal Folder As FolderDeleteOptions)
        Name = Folder.KeyName
        FolderPath = Folder.FolderPath
        TimeValue = Folder.TimeValue
        TimeUnits = Folder.TimeUnits
        Disabled = Folder.Disabled
        'CurrentIndex = -1
    End Sub

    Public Sub New(ByVal key As RegistryKey)
        Name = key.Name.Substring(key.Name.IndexOf(RegistryStoredFolderValuesCollection.KEY_PATH) + _
                                  RegistryStoredFolderValuesCollection.KEY_PATH.Length + 1)
        FolderPath = CType(key.GetValue(FOLDER_PATH_NAME, ""), String)
        TimeValue = CType(key.GetValue(TIME_VALUE_NAME, 0), Integer)
        TimeUnits = CType(key.GetValue(TIME_UNITS_NAME, 0), Byte)
        Disabled = CType(key.GetValue(DISABLED_NAME, 0), Boolean)
        'CurrentIndex = -1
    End Sub

    Public Shared Operator =(ByVal x As RegistryStoredFolderValues, ByVal y As RegistryStoredFolderValues) As Boolean
        Return (x.Name = y.Name And x.FolderPath = y.FolderPath And x.TimeUnits = y.TimeUnits _
                And x.TimeValue = y.TimeValue And x.Disabled = y.Disabled)
    End Operator

    Public Shared Operator <>(ByVal x As RegistryStoredFolderValues, ByVal y As RegistryStoredFolderValues) As Boolean
        Return (Not x = y)
    End Operator

    Public Shared Operator =(ByVal x As RegistryStoredFolderValues, ByVal y As FolderDeleteOptions) As Boolean
        Return (x.Name = y.KeyName And x.FolderPath = y.FolderPath And x.TimeValue = y.TimeValue _
                And x.TimeUnits = y.TimeUnits And x.Disabled = y.Disabled)
    End Operator

    Public Shared Operator <>(ByVal x As RegistryStoredFolderValues, ByVal y As FolderDeleteOptions) As Boolean
        Return (Not x = y)
    End Operator

    Public Shared Operator =(ByVal x As FolderDeleteOptions, ByVal y As RegistryStoredFolderValues) As Boolean
        Return (x.KeyName = y.Name And x.FolderPath = y.FolderPath And x.TimeValue = y.TimeValue _
                And x.TimeUnits = y.TimeUnits And x.Disabled = y.Disabled)
    End Operator

    Public Shared Operator <>(ByVal x As FolderDeleteOptions, ByVal y As RegistryStoredFolderValues) As Boolean
        Return (Not x = y)
    End Operator

    Public Function IsValid() As Boolean
        Return (If(Name, "") <> "" And If(FolderPath, "") <> "" And TimeValue > 0 And TimeUnits < 4)
    End Function

    Public Sub SetAllValues(ByVal key As RegistryKey)
        key.SetValue(FOLDER_PATH_NAME, FolderPath, RegistryValueKind.String)
        key.SetValue(TIME_VALUE_NAME, TimeValue, RegistryValueKind.DWord)
        key.SetValue(TIME_UNITS_NAME, TimeUnits, RegistryValueKind.DWord)
        key.SetValue(DISABLED_NAME, If(Disabled, 1, 0), RegistryValueKind.DWord)
        key.Close()
    End Sub

    Public ReadOnly Property OldestValidDate As Date
        Get
            Select Case TimeUnits
                Case 0 : Return Now.AddDays(-1 * TimeValue)
                Case 1 : Return Now.AddDays(-7 * TimeValue)
                Case 2 : Return Now.AddMonths(-1 * TimeValue)
                Case 3 : Return Now.AddYears(-1 * TimeValue)
                Case Else : Throw New ArgumentException("Unknown unit. Cannot tell when to delete.", "TimeUnits")
            End Select
        End Get
    End Property
End Structure